using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using Habanero.Faces.Base;
using Habanero.Faces.Win;
using DockStyle=Habanero.Faces.Base.DockStyle;
using ScrollBars=Habanero.Faces.Base.ScrollBars;

namespace FireStarter.Test.CodeGeneration
{
    public static class TestUtilsCodeGen
    {
        private static string _tempTestProjectFolder = "TestProjects";

        public static string TempTestProjectFolder
        {
            get { return _tempTestProjectFolder; }
            set { _tempTestProjectFolder = value; }
        }

        public static void ShowCodeInForm(string text)
        {
            IFormHabanero outputCode = new FormWin();
            ITextBox textBox = new TextBoxWin();
            textBox.Multiline = true;
            textBox.ScrollBars = ScrollBars.Both;
            textBox.Text = text;
            textBox.Dock = DockStyle.Fill;
            textBox.Font = new Font(FontFamily.GenericMonospace, 9);
            outputCode.Controls.Add(textBox);
            outputCode.Height = 700;
            outputCode.Width = 1200;
            outputCode.ShowDialog();
        }

        public static string GetRandomWhiteSpace()
        {
            var count = GetRandomInt(10);
            string text = "";
            for (int i = -1; i < count; i++)
            {
                text += " \t\r\n";
            }
            return text;
        }

        public static int GetRandomInt()
        {
            return GetRandomInt(int.MaxValue);
        }

        public static int GetRandomInt(int maxValue)
        {
            return new Random().Next(0, maxValue);
        }

        public static string GetRandomString()
        {
            return Guid.NewGuid().ToString("N");
        }

        public static string GetRootedPath(string path)
        {
            if (Path.IsPathRooted(path)) return path;
            return Path.Combine(Environment.CurrentDirectory, path);
        }

        public static string GetRandomProjectFileName()
        {
            return Path.Combine(TempTestProjectFolder, string.Format("{0}\\{1}.csproj", GetRandomString(), GetRandomString()));
        }

        public static ProjectFileManager CreateProjectFile(string projectFileName)
        {
            if (projectFileName == null) throw new ArgumentNullException("projectFileName");
            ProjectFileManager projectFileManager = new ProjectFileManager(projectFileName, OutputType.Library, CodeTemplateEnum.CSharpVisualStudio2005);
            projectFileManager.SaveProjectFile();
            return projectFileManager;
        }

        public static DMRelationship CreateModelRelationship(DMClass ownerClass, DMClass relatedClass, bool isMultiple)
        {
            DMRelationship relationship = new DMRelationship();
            relationship.Cardinality = isMultiple ? Cardinality.Multiple : Cardinality.Single;
            relationship.RelatedClass = relatedClass;
            ownerClass.OwnerRelationships.Add(relationship);
            return relationship;
        }

        public static DMClass CreateModelClass(string className)
        {
            DMClass parentClass = new DMClass();
            parentClass.ClassNameBO = className;
            return parentClass;
        }

        public static DMClass CreateModelClassOnProject(DMAssembly modelAssembly, string className)
        {
            DMClass dmClass = CreateModelClass(className);
            modelAssembly.Classes.Add(dmClass);
            //dmClass.Assembly = modelAssembly;
            return dmClass;
        }

        public static DMProperty CreatePropertyOnClass(DMClass dmClass, string propertyName)
        {
            DMProperty modelProperty = new DMProperty();
            modelProperty.PropertyName = propertyName;
            modelProperty.Class = dmClass;
            dmClass.Properties.Add(modelProperty);
            return modelProperty;
        }

        public static DMProperty CreatePropertyOnClass(DMClass dmClass, string propertyName, string typeName)
        {
            DMProperty modelProperty = CreatePropertyOnClass(dmClass, propertyName);
            modelProperty.PropertyType=new DMPropertyType();
            modelProperty.PropertyType.PropertyTypeName = typeName;
            modelProperty.PropertyType.AssemblyName = "System";
            return modelProperty;
        }
        
        public static List<DMClass> GetParentChildHeirarchy(out List<DMClass> expectedModelClassesInDeletionOrder)
        {
            DMAssembly dmAssembly = new DMAssembly(GetRandomString());
            DMClass class1 = CreateModelClass("Class1",dmAssembly);
            DMClass class2 = CreateModelClass("Class2", dmAssembly);
            DMClass class2child = CreateModelClass("Class2Child", dmAssembly);
            DMClass class2grandchild = CreateModelClass("Class2Grandchild", dmAssembly);
            DMClass class3 = CreateModelClass("Class3", dmAssembly);
            DMClass class3child = CreateModelClass("Class3Child", dmAssembly);
            DMClass class4 = CreateModelClass("Class4", dmAssembly);

            CreateModelRelationship(class2, class2child, true);
            CreateModelRelationship(class2child, class2grandchild, true);
            CreateModelRelationship(class3, class3child, true);

            // Did have this mixed up order, but with AllClasses getting returned in alphabetical
            // order, we had tests failing and chose to assume alphabetical order
            //List<DMClass> modelClasses = new List<DMClass> { class3, class1, class2, class2child, class3child, class4, class2grandchild };
            //expectedModelClassesInDeletionOrder = new List<DMClass> { class3child, class3, class1, class2grandchild, class2child, class2, class4 };

            List<DMClass> modelClasses = new List<DMClass> { class1, class2, class2child, class2grandchild, class3, class3child, class4 };
            expectedModelClassesInDeletionOrder = new List<DMClass> { class1, class2grandchild, class2child, class2, class3child, class3, class4 };
            
            return modelClasses;
        }

        private static DMClass CreateModelClass(string className, DMAssembly dmAssembly)
        {
            DMClass modelClass = CreateModelClass(className);
            modelClass.Assembly = dmAssembly;
            return modelClass;
        }

        public static DMProperty CreatePKPropertyOnClass(DMClass modelClass, string propertyName)
        {
            DMProperty modelProperty = CreatePropertyOnClass(modelClass, propertyName);
            DMObjectIdentity objectIdentity = new DMObjectIdentity();
            objectIdentity.Properties.Add(modelProperty);
            objectIdentity.IsObjectID = false;
            objectIdentity.Class = modelClass;
            return modelProperty;
        }

        public static void SetPropertyType(DMProperty modelProperty, string assemblyName, string typeName)
        {
            DMPropertyType dmPropertyType = new DMPropertyType();
            dmPropertyType.PropertyTypeName = typeName;
            dmPropertyType.AssemblyName = assemblyName;
            modelProperty.PropertyType = dmPropertyType;
        }
    }
}